"""
V4
多线程
同时执行左右摇杆命令
输入队列
"""
import pygame
import vgamepad as vg
import time
import threading
import keyboard
from queue import Queue, Empty

# 单个命令执行时长
step = 1.0

# 命令映射
command_map = {
    'w': ('left', 0.0, 1.0, "左摇杆向上移动"),
    's': ('left', 0.0, -1.0, "左摇杆向下移动"),
    'a': ('left', -1.0, 0.0, "左摇杆向左移动"),
    'd': ('left', 1.0, 0.0, "左摇杆向右移动"),
    't': ('right', 0.0, 1.0, "右摇杆向上移动"),
    'b': ('right', 0.0, -1.0, "右摇杆向下移动"),
    'l': ('right', -1.0, 0.0, "右摇杆向左移动"),
    'r': ('right', 1.0, 0.0, "右摇杆向右移动"),
    'A': ('button', vg.XUSB_BUTTON.XUSB_GAMEPAD_A, "A按钮"),
    'B': ('button', vg.XUSB_BUTTON.XUSB_GAMEPAD_B, "B按钮"),
    'X': ('button', vg.XUSB_BUTTON.XUSB_GAMEPAD_X, "X按钮"),
    'Y': ('button', vg.XUSB_BUTTON.XUSB_GAMEPAD_Y, "Y按钮"),
    'n': ('empty')
}

def execute_command_sequence_init(command_string):
    print("开始执行命令序列:", command_string)
    
    # 创建虚拟手柄
    gamepad = vg.VX360Gamepad()
    print("虚拟手柄创建成功")
    

    
    # 执行每个命令
    for i, char in enumerate(command_string):
        if char in command_map:
            command = command_map[char]
            print(f"执行第{i+1}个命令: {char} - {command[2]}")
            
            if command[0] == 'left':  # 左摇杆命令
                _, x_axis, y_axis, _ = command
                gamepad.left_joystick_float(x_value_float=x_axis, y_value_float=y_axis)
                gamepad.update()
                print(f"左摇杆移动到: X={x_axis}, Y={y_axis}")
                time.sleep(1)  # 执行1秒
                
                # 重置摇杆
                gamepad.left_joystick_float(x_value_float=0.0, y_value_float=0.0)
                gamepad.update()
                print("左摇杆回中")
            
            elif command[0] == 'right':  # 右摇杆命令
                _, x_axis, y_axis, _ = command
                gamepad.right_joystick_float(x_value_float=x_axis, y_value_float=y_axis)
                gamepad.update()
                print(f"右摇杆移动到: X={x_axis}, Y={y_axis}")
                time.sleep(1)  # 执行1秒
                
                # 重置摇杆
                gamepad.right_joystick_float(x_value_float=0.0, y_value_float=0.0)
                gamepad.update()
                print("右摇杆回中")
                
            elif command[0] == 'button':  # 按钮命令
                _, button, _ = command
                gamepad.press_button(button=button)
                gamepad.update()
                print(f"按下按钮: {command[2]}")
                time.sleep(0.9)  # 短暂按下
                
                gamepad.release_button(button=button)
                gamepad.update()
                print(f"释放按钮: {command[2]}")
                time.sleep(0.1)  # 总共1秒
            
            # 命令间短暂间隔
            if i < len(command_string) - 1:
                time.sleep(0.1)
        time.sleep(10)
        
    time.sleep(10)
    
    # 清理
    gamepad.reset()
    gamepad.update()
    print("命令序列执行完成")

def init():
    time.sleep(5)
    command_sequence = "A左A上"
    execute_command_sequence_init(command_sequence)


class GamepadController:
    def __init__(self):
        self.gamepad = vg.VX360Gamepad()
        self.running = True
        self.paused = False
        
        # 命令缓冲区队列
        self.left_command_queue = Queue()
        self.right_command_queue = Queue()
        
        # 执行线程
        self.left_thread = None
        self.right_thread = None
        self.monitor_thread = None
        
        # 最后输入时间
        self.last_input_time = time.time()
        
        print("虚拟手柄创建成功")
    
    def add_left_command(self, command_char):
        """向左侧命令缓冲区添加命令"""
        if command_char in ['w', 'a', 's', 'd', 'A', 'B', 'X', 'Y', 'n']:
            self.left_command_queue.put(command_char)
            print(f"左侧命令已添加: {command_char}")
    
    def add_right_command(self, command_char):
        """向右侧命令缓冲区添加命令"""
        if command_char in ['t', 'b', 'l', 'r', 'n']:
            self.right_command_queue.put(command_char)
            print(f"右侧命令已添加: {command_char}")
    
    def add_left_commands(self, command_string):
        """向左侧命令缓冲区添加多个命令"""
        for char in command_string:
            if char in ['w', 'a', 's', 'd', 'A', 'B', 'X', 'Y', 'n']:
                self.left_command_queue.put(char)
        print(f"左侧批量命令已添加: {command_string}")
    
    def add_right_commands(self, command_string):
        """向右侧命令缓冲区添加多个命令"""
        for char in command_string:
            if char in ['t', 'b', 'l', 'r', 'n']:
                self.right_command_queue.put(char)
        print(f"右侧批量命令已添加: {command_string}")
    
    def clear_left_commands(self):
        """清空左侧命令缓冲区"""
        while not self.left_command_queue.empty():
            try:
                self.left_command_queue.get_nowait()
            except Empty:
                break
        print("左侧命令缓冲区已清空")
    
    def clear_right_commands(self):
        """清空右侧命令缓冲区"""
        while not self.right_command_queue.empty():
            try:
                self.right_command_queue.get_nowait()
            except Empty:
                break
        print("右侧命令缓冲区已清空")
    
    def pause(self):
        """暂停执行"""
        self.paused = True
        print("执行已暂停")
    
    def resume(self):
        """恢复执行"""
        self.paused = False
        print("执行已恢复")
    
    def stop(self):
        """停止执行"""
        self.running = False
        print("执行已停止")
        
        # 清空缓冲区
        self.clear_left_commands()
        self.clear_right_commands()
        
        # 重置所有摇杆和按钮
        self.gamepad.left_joystick_float(x_value_float=0.0, y_value_float=0.0)
        self.gamepad.right_joystick_float(x_value_float=0.0, y_value_float=0.0)
        self.gamepad.update()
        
    def wait_for_completion(self):
        """等待所有命令执行完成"""
        self.left_command_queue.join()
        self.right_command_queue.join()
        print("所有命令执行完成")
        
    def execute_left_commands(self):
        """执行左侧命令（持续从缓冲区读取）"""
        print("左侧命令执行线程启动")
        
        while self.running:
            # 检查暂停状态
            while self.paused and self.running:
                time.sleep(0.1)
            
            if not self.running:
                break
                
            try:
                # 从队列获取命令（非阻塞，等待0.1秒）
                char = self.left_command_queue.get(timeout=0.1)
                
                if char in command_map:
                    command = command_map[char]
                    
                    if command[0] == 'left':
                        _, x_axis, y_axis, _ = command
                        
                        # 设置左摇杆位置
                        self.gamepad.left_joystick_float(x_value_float=x_axis, y_value_float=y_axis)
                        self.gamepad.update()
                        print(command[3])
                        
                        time.sleep(step)  # 保持位置一段时间
                        
                        # 重置左摇杆
                        self.gamepad.left_joystick_float(x_value_float=0.0, y_value_float=0.0)
                        self.gamepad.update()
                        print("左摇杆回中")
                    
                    elif command[0] == 'button':
                        _, button, _ = command
                        
                        self.gamepad.press_button(button=button)
                        self.gamepad.update()
                        print(f"按下按钮: {command[2]}")
                        
                        time.sleep(step)  
                        
                        # 释放按钮
                        self.gamepad.release_button(button=button)
                        self.gamepad.update()
                        print(f"释放按钮: {command[2]}")
                        
                    else:
                        time.sleep(step)  
                      
                    self.last_input_time = time.time()  
                
                # 标记任务完成
                self.left_command_queue.task_done()
                
            except Empty:
                # 队列为空，继续等待
                continue
            except Exception as e:
                print(f"左侧命令执行错误: {e}")
                continue
        
        print("左侧命令执行线程退出")
    
    def execute_right_commands(self):
        """执行右侧命令（持续从缓冲区读取）"""
        print("右侧命令执行线程启动")
        
        while self.running:
            # 检查暂停状态
            while self.paused and self.running:
                time.sleep(0.1)
            
            if not self.running:
                break
                
            try:
                # 从队列获取命令（非阻塞，等待0.1秒）
                char = self.right_command_queue.get(timeout=0.1)
                
                if char in command_map:
                    if command_map[char][0] == 'right':
                        command = command_map[char]
                        _, x_axis, y_axis, _ = command
                        
                        # 设置右摇杆位置
                        self.gamepad.right_joystick_float(x_value_float=x_axis, y_value_float=y_axis)
                        self.gamepad.update()
                        print(command[3])
                        
                        time.sleep(step)  # 保持位置一段时间
                        
                        # 重置右摇杆
                        self.gamepad.right_joystick_float(x_value_float=0.0, y_value_float=0.0)
                        self.gamepad.update()
                        print("右摇杆回中")
                        
                    else: 
                        time.sleep(step)

                    self.last_input_time = time.time()
                
                # 标记任务完成
                self.right_command_queue.task_done()
                
            except Empty:
                # 队列为空，继续等待
                continue
            except Exception as e:
                print(f"右侧命令执行错误: {e}")
                continue
        
        print("右侧命令执行线程退出")
    
    def auto_stop_monitor(self):
        """自动停止监控线程"""
        while self.running:
            current_time = time.time()
            
            # 检查两个队列是否都为空且30秒无新输入
            if (self.left_command_queue.empty() and 
                self.right_command_queue.empty() and 
                current_time - self.last_input_time > 30):
                print("两个队列都为空且30秒无新输入，自动断开...")
                self.wait_for_completion()
                self.stop()
                break
                
            time.sleep(1)
            
    def start_execution(self):
        """启动命令执行线程"""
        if self.left_thread is None or not self.left_thread.is_alive():
            self.left_thread = threading.Thread(target=self.execute_left_commands)
            self.left_thread.daemon = True
            self.left_thread.start()
            print("左侧执行线程已启动")
        
        if self.right_thread is None or not self.right_thread.is_alive():
            self.right_thread = threading.Thread(target=self.execute_right_commands)
            self.right_thread.daemon = True
            self.right_thread.start()
            print("右侧执行线程已启动")
    
        if self.monitor_thread is None or not self.monitor_thread.is_alive():
            self.monitor_thread = threading.Thread(target=self.auto_stop_monitor)
            self.monitor_thread.daemon = True
            self.monitor_thread.start()
            print("自动停止监控线程已启动")



if __name__ == "__main__":
    controller = GamepadController()
    # 添加键盘监听用于暂停/恢复/停止
    keyboard.add_hotkey('p', controller.pause)
    keyboard.add_hotkey('r', controller.resume)
    keyboard.add_hotkey('s', controller.stop)
    keyboard.add_hotkey('c', controller.clear_left_commands)  # 清空左侧
    keyboard.add_hotkey('v', controller.clear_right_commands)  # 清空右侧
    
    print("按 P 暂停，按 R 继续，按 S 停止")
    print("按 C 清空左侧命令，按 V 清空右侧命令")
    
    
    time.sleep(5)
    
    # 启动执行线程
    controller.start_execution()
    
    # 添加左侧命令
    controller.add_left_commands("wswsAwwssad")
    controller.add_left_command('B')
    controller.add_left_command('X')
    
    # 添加右侧命令
    controller.add_right_commands("lllrrr")
    controller.add_right_command('rr')
    controller.add_right_command('ll')
    
    # 等待一段时间后添加更多命令
    time.sleep(3)
    controller.add_left_commands("ddddwwww")
    controller.add_right_commands("rrrrrtttt")
    
    # 保持程序运行
    try:
        last_input_time = time.time()  # 记录最后输入时间
        
        while True:
            current_time = time.time()
            
            # 检查两个队列是否都为空且30秒无新输入
            if (controller.left_command_queue.empty() and 
                controller.right_command_queue.empty() and 
                current_time - last_input_time > 30):
                print("两个队列都为空且30秒无新输入，自动断开...")
                controller.wait_for_completion()
                controller.stop()
                break
                
            time.sleep(1)
            
    except KeyboardInterrupt:
        controller.stop()
        print("程序退出")
    
